import time
from vdsClient import BLANK_UUID
from storageConnectionTestUtils import disconnectFromStorage, connectToStorage
from storageDomainTestUtils import destroyDomainTargets
from spmTestUtils import eSpmStatus

def retry(action, tries, retryEvery=1, expectedException=Exception):
    """
    Try to preform action a number of times until it succeedes.

    When fails all tries throws the last exception cought.

    :param action: The action to perform
    :type action: callable
    :param tries: The number of times to try
    :param retryEvery: How much secods to wait between tries
    :param expectedException: The exception that is raise if the action fails.
    :type expectedException: Exception

    :returns: The result of *action*
    """
    i = 0
    passed = False
    while not passed:
        i += 1
        try:
            res = action()
            passed = True
        except expectedException:
            if i < tries:
                time.sleep(retryEvery)
                continue
            raise

    return res

def cleanVdsm(client, hostID, conList):
    """
    Tries to clean up as much as it can.

    :param client: Connection to the vdsClient you want to clean
    :param hostID: The hostID of that VDSM
    :param conList: The list of connections.
                    Should be removed once we can retrieve the list of current active connections
    """
    connectToStorage(client, conList) # The test might fail the client is not connected

    # Release Pools
    connectedPools = client.getConnectedStoragePoolsList()['poollist']
    notOwnedDomains = []
    for connectedPool in connectedPools:
        client.refreshStoragePool(connectedPool, BLANK_UUID, BLANK_UUID)
        resp = client.getStoragePoolInfo(connectedPool)
        if resp['status']['code'] != 0:
            continue

        spmStatus = client.getSpmStatus(connectedPool)
        if 'spm_st' in spmStatus:
            status = spmStatus['spm_st']

            masterDomain = resp['info']['master_uuid']
            isSpmRunning = (status['spmStatus'] == eSpmStatus.Running)
            if isSpmRunning:
                # Am I the SPM
                if hostID == status['spmId']:
                    # Deactivate domains
                    domainInfos = resp['dominfo']

                    # Make master domain appear last
                    domains = domainInfos.keys()
                    domains.remove(masterDomain)
                    domains.append(masterDomain)

                    for domain in domains:
                        isActive = (domainInfos[domain]['status'] == 'Active')
                        if isActive:
                            client.deactivateStorageDomain(domain, connectedPool, BLANK_UUID, -1)

                    # Destroy the pool
                    resp = client.destroyStoragePool(connectedPool, hostID, "IGNORED")
                    if resp['status']['code'] == 0:
                        continue

            # Is someone the SPM?
            if hostID != status['spmId'] and status['spmId'] != -1 :
                notOwnedDomains.extend(client.getStorageDomainsList(connectedPool)['domlist'])

        # Disconnect
        resp = client.disconnectStoragePool(connectedPool, hostID, "IGNORED")
        if resp['status']['code'] != 0:
            print "Disconnect storage pool '%s' (%s)" % (domain, resp)

    # Delete domains
    domainList = client.getStorageDomainsList()['domlist']
    domainTargets = []
    for domain in domainList:
        if domain in notOwnedDomains:
            continue

        resp = client.getStorageDomainInfo(domain)
        if 'info' in resp:
            domainInfo = resp['info']
            if domainInfo["type"] in ["ISCSI", "FCP"]:
                domainTargets.append(domainInfo["vguuid"])
            elif domainInfo["type"] in ["NFS", "LOCALFS"]:
                domainTargets.append(domainInfo["remotePath"])
        else:
            print "no dominfo", resp

        resp = client.formatStorageDomain(domain, True)
        if resp['status']['code'] != 0:
            print "Could not format domain '%s' (%s)" % (domain, resp)

    destroyDomainTargets(client, domainTargets)
    disconnectFromStorage(client, conList)

